package com.bupt.secret.utils;

import com.bupt.secret.constant.BuptConstant;
import com.bupt.secret.dto.*;
import com.bupt.secret.enums.BuptErrorCodeEnum;
import com.bupt.secret.execption.BuptException;
import com.bupt.secret.service.BuptSecretService;
import lombok.Value;

import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;


/**
 * @author ShiShuMin
 * @version v1.0
 * @ClassName BuptClientUtil
 * @Date: 2024/8/30 10:17
 * @Description:
 */
public class BuptClientUtil {

    // SO对象
    private static volatile BuptSecretService.GMTLibrary instance;
    private static volatile BuptSecretService.ServerLibrary serverLibrary;

    // 设备句柄
    private static Long deviceHandle;

    /**
     * @desc 打开设备
     * @author shishumin
     * @date 2024/8/30 10:11
     */
    public static synchronized BuptResultDto openDevice() {
        isCheckInstance();
        long[] deviceHandleArr = new long[1];
        int status = instance.SDF_OpenDevice(deviceHandleArr);
        if (BuptConstant.OK == status) {
            deviceHandle = deviceHandleArr[0];
            return BuptResultDto.ok(deviceHandle);
        }
        return BuptResultDto.error(status);
    }

    /**
     * @desc 打开回话
     * @author shishumin
     * @date 2024/8/30 10:22
     */
    public static BuptResultDto openSession() {
        if (deviceHandle == null || deviceHandle == 0) {
            BuptResultDto resultDto = openDevice();
            if (resultDto.getCode() == 0) {
                deviceHandle = Long.valueOf(resultDto.getData().toString());
            }
        }
        long[] sessionHandleArr = new long[1];
        int status = instance.SDF_OpenSession(deviceHandle, sessionHandleArr);
        if (BuptConstant.OK == status) {
            return BuptResultDto.ok(sessionHandleArr[0]);
        }
        return BuptResultDto.error(status);
    }

    /**
     * @desc 统一参数校验
     * @author shishumin
     * @date 2024/9/6 10:44
     */
    public static void isCheckInstance() {
        if (instance == null) {
            serverLibrary = BuptSecretService.ServerLibrary.INSTANCE;
            instance = BuptSecretService.GMTLibrary.INSTANCE;
        }
    }

    /**
     * @desc 统一参数校验
     * @author shishumin
     * @date 2024/9/6 10:44
     */
    public static void isCheckSessionHandle(long sessionHandle) {
        isCheckInstance();
        if (sessionHandle == 0) {
            throw new BuptException(BuptErrorCodeEnum.BUPT_SESSION_IS_NULL.getDescription());
        }
    }

    public static void isCheckKeyHandle(long hKeyHandle) {
        if (hKeyHandle <= 0) {
            throw new BuptException(BuptErrorCodeEnum.BUPT_HKEYHANDLE_IS_NULL.getDescription());
        }
    }

    /**
     * @desc 关闭设备
     * @author shishumin
     * @date 2024/8/30 16:22
     */
    public static BuptResultDto closeDevice() {
        int status = instance.SDF_CloseDevice(deviceHandle);
        return BuptResultDto.status(status);
    }

    /**
     * @desc 关闭回话
     * @author shishumin
     * @date 2024/8/30 16:22
     */
    public static BuptResultDto closeSession(long sessionHandle) {
        int status = instance.SDF_CloseSession(sessionHandle);
        if (deviceHandle != null) {
            closeDevice();
            deviceHandle = null;
        }
        return BuptResultDto.status(status);
    }

    /**
     * @desc 获取设备信息
     * @author shishumin
     * @date 2024/8/30 10:28
     */
    public static BuptResultDto getDeviceInfo(long sessionHandle) {
        isCheckSessionHandle(sessionHandle);
        DeviceInfo deviceInfo = new DeviceInfo();
        int status = instance.SDF_GetDeviceInfo(sessionHandle, deviceInfo);
        if (BuptConstant.OK == status) {
            return BuptResultDto.ok(deviceInfo);
        }
        return BuptResultDto.status(status);
    }

    /**
     * @param length 随机数长度 c语言是无符号的（每一位是0~255）之间产生
     * @return String 16进制的结果
     * @desc 获取随机数
     * @author shishumin
     * @date 2024/8/30 14:10
     */
    public static BuptResultDto generateRandom(long sessionHandle, int length) {
        isCheckSessionHandle(sessionHandle);
        // 创建字节数组来存储生成的随机数据
        byte[] randomData = new byte[length];

        int status = instance.SDF_GenerateRandom(sessionHandle, length, randomData);
        // 16进制处理
//        StringBuffer stringBuffer = new StringBuffer();
//        for (byte randomDatum : randomData) {
//
//            // byte[-127~128]， 直接强转int得到-1，不是255
//            int javaReceive = randomDatum;
//
//            // 转int[0~255]
//            int expected = javaReceive & 0xff;
//
//            // 转16进制
//            String hexString = Integer.toHexString(expected).toUpperCase();
//            stringBuffer.append(hexString);
//        }
        return status == 0 ? BuptResultDto.ok(randomData) : BuptResultDto.error(status);
    }

    /**
     * @desc 获取RSA签名公钥
     * @author shishumin
     * @date 2024/8/30 15:10
     * 参数： hSessionHandle【in】 已经打开会话句柄
     * uiKeyIndex[in]     密码设备存储私钥索引（1.RSA, 2.SM2）服务端初始化可配置
     * pucPublicKey[out]  RSA公钥结构
     */
    public static BuptResultDto<RSArefPublicKey> exportSignPublicKeyRSA(long sessionHandle, int uiKeyIndex) {
        isCheckSessionHandle(sessionHandle);
        // 创建字节数组来存储生成的随机数据
        RSArefPublicKey rsArefPublicKey = new RSArefPublicKey();
        int status = instance.SDF_ExportSignPublicKey_RSA(sessionHandle, uiKeyIndex, rsArefPublicKey);
        if (BuptConstant.OK == status) {
            return BuptResultDto.ok(rsArefPublicKey);
        }
        return BuptResultDto.error(status);
    }

    /**
     * @desc 获取RSA加密公钥
     * @author shishumin
     * @date 2024/8/30 15:07
     * 参数： hSessionHandle【in】 已经打开会话句柄
     * uiKeyIndex[in]     密码设备存储私钥索引（1.RSA, 2.SM2）服务端初始化可配置
     * pucPublicKey[out]  RSA公钥结构
     */
    public static BuptResultDto<RSArefPublicKey> exportEncPublicKeyRSA(long sessionHandle, int uiKeyIndex) {
        isCheckSessionHandle(sessionHandle);
        // 公钥对象
        RSArefPublicKey rsArefPublicKey = new RSArefPublicKey();
        int status = instance.SDF_ExportEncPublicKey_RSA(sessionHandle, uiKeyIndex, rsArefPublicKey);
        if (BuptConstant.OK == status) {
            return BuptResultDto.ok(rsArefPublicKey);
        }
        return BuptResultDto.error(status);
    }

    /**
     * @desc 请求密码设备产生指定模长的RSA密钥对
     * @author shishumin
     * @date 2024/8/30 17:31
     * 参数： hSessionHandle【in】 已经打开会话句柄
     * uiKeyBits【in】      指定密钥模长(1024, 2048)
     * pucPublicKey[out]    RSA公钥结构
     * pucPrivateKey[out]   RSA私钥结构
     * 返回值：0  成功； 非0  失败，返回错误代码
     */
    public static BuptResultDto<RSArefCommonKeyBo> generateKeyPairRSA(long sessionHandle, int uiKeyBits) {
        isCheckSessionHandle(sessionHandle);

        // 公私钥对象
        RSArefPublicKey rsArefPublicKey = new RSArefPublicKey();
        CipherRSArefPrivateKey rsArefPrivateKey = new CipherRSArefPrivateKey();
        int status = instance.SDF_GenerateKeyPair_RSA(sessionHandle, uiKeyBits, rsArefPublicKey, rsArefPrivateKey);
        if (BuptConstant.OK == status) {
            RSArefCommonKeyBo commonKey = new RSArefCommonKeyBo();
            commonKey.setRsArefPublicKey(rsArefPublicKey);
            commonKey.setRsArefPrivateKey(rsArefPrivateKey);
            return BuptResultDto.ok(commonKey);
        }
        return BuptResultDto.error(status);
    }

    /**
     * 功能描述：生成RSA密钥对,私钥用口令加密输出
     * 参数： hSessionHandle [in]        与设备建立的会话句柄
     * uiKeyBits      [in]        公钥模长（RSA:1024或者2048）
     * pin            [in]        口令
     * pinLen         [in]        口令长度
     * secertKeyAlgID [in]        保密密钥算法标识
     * pucPublicKey   [out]       公钥
     * pucKey         [out]       私钥密文
     * 返回值：0  成功； 非0  失败，返回错误代码
     */
    public static BuptResultDto<RSArefCommonKeyBo> generateKeyPairRSAV2(long sessionHandle, int uiKeyBits, String pin, int secertKeyAlgID) {
        isCheckSessionHandle(sessionHandle);


        byte[] bytesPin = pin.getBytes(StandardCharsets.UTF_8);
        // 公私钥对象
        RSArefPublicKey rsArefPublicKey = new RSArefPublicKey();
        CipherRSArefPrivateKey privateKey = new CipherRSArefPrivateKey();
//        int status = 1;
        int status = instance.GenerateKeyPair_RSA(sessionHandle, uiKeyBits, bytesPin, bytesPin.length, secertKeyAlgID, rsArefPublicKey, privateKey);
        if (BuptConstant.OK == status) {
            RSArefCommonKeyBo commonKey = new RSArefCommonKeyBo();
            commonKey.setRsArefPublicKey(rsArefPublicKey);
            commonKey.setRsArefPrivateKey(privateKey);
            return BuptResultDto.ok(commonKey);

        }
        return BuptResultDto.error(status);
    }

    /**
     *  功能描述：导入RSA密钥对,私钥已做加密处理
     *  参数： hSessionHandle [in]        与设备建立的会话句柄
     *         uiKeyIndex     [in]        密钥索引（自定义索引，值小于255）
     *         pin            [in]        口令
     *         pinLen         [in]        口令长度
     *         secertKeyAlgID [in]        保密密钥算法标识
     *         pucPublicKey   [in]        公钥
     *         pucKey         [in]       私钥密文
     * 返回值：0  成功； 非0  失败，返回错误代码
     */
    public static BuptResultDto importKeyPairRSAV2(long sessionHandle, int uiKeyBits, String pin,
                                                                        int secertKeyAlgID, RSArefPublicKey rsArefPublicKey,
                                                                        CipherRSArefPrivateKey privateKey) {
        isCheckSessionHandle(sessionHandle);
        byte[] bytesPin = pin.getBytes(StandardCharsets.UTF_8);
        int status = instance.ImportKeyPair_RSA(sessionHandle, uiKeyBits, bytesPin, bytesPin.length, secertKeyAlgID, rsArefPublicKey, privateKey);
        System.out.println("status:" + status);
        return BuptResultDto.error(status);
    }

    /**
     * 6.3.5
     * 功能描述：生成会话密钥并用外部RSA公钥加密输出
     * 参数： hSessionHandle【in】 已经打开会话句柄
     * uiKeyBits【in】      指定产生会话密钥长度(16整数倍)
     * pucPublicKey【in】   输入的外部RSA公钥结构
     * pucKey[out]          缓冲区指针，用于存放返回的密钥密文
     * puiKeyLength[out]    返回的密钥密文长度
     * phKeyHandle[out]     返回的密钥句柄
     * 返回值：0  成功； 非0  失败，返回错误代码
     *
     * @author shishumin
     * @date 2024/8/31 19:57
     */
    public static BuptResultDto<RSASessionKeyBo> generateKeyWithEPKRSA(long sessionHandle, int uiKeyBits, RSArefPublicKey rsArefPublicKey) {
        // 参数校验
        isCheckSessionHandle(sessionHandle);
        if (uiKeyBits <= 0) {
            throw new BuptException(BuptErrorCodeEnum.BUPT_PUI_KEY_LENGTH_ZERO.getDescription());
        }
        if (rsArefPublicKey == null) {
            throw new BuptException(BuptErrorCodeEnum.BUPT_RSAREFPUBLICKEY_NULL.getDescription());
        }

        // 创建一个int数组用于接收密钥密文长度
        int[] puiKeyLength = new int[1];
        // 密钥密文
        byte[] pucKey = new byte[1024];

        // 创建一个long数组用于接收密钥句柄
        long[] phKeyHandle = new long[1];

        int status = instance.SDF_GenerateKeyWithEPK_RSA(sessionHandle, uiKeyBits, rsArefPublicKey, pucKey, puiKeyLength, phKeyHandle);
        if (BuptConstant.OK == status) {
            RSASessionKeyBo sessionKeyBo = new RSASessionKeyBo();
            sessionKeyBo.setPucKey(pucKey);
            sessionKeyBo.setPuiKeyLength(puiKeyLength[0]);
            sessionKeyBo.setPhKeyHandle(phKeyHandle[0]);
            return BuptResultDto.ok(sessionKeyBo);
        }
        return BuptResultDto.error(status);
    }

    /**
     * @desc 导入会话密钥并用内部RSA私钥解密
     * @author shishumin
     * @date 2024/9/5 09:52
     * 6.3.6(和6.3.5是对应关系)
     * 功能描述：导入会话密钥并用内部RSA私钥解密
     * 参数： hSessionHandle【in】 已经打开会话句柄
     * uiISKIndex【in】     密码设备内部存储加密私钥的索引值
     * pucKey[in]          输入会话密钥
     * puiKeyLength[in]    密钥密文长度
     * phKeyHandle[out]     返回的密钥句柄
     * 返回值：0  成功； 非0  失败，返回错误代码
     * 备注： 公钥加密数据时填充方式按照ＰＫＣＳ＃１ｖ １． ５的要求进行
     **/
    public static BuptResultDto importKeyWithISKRSA(long sessionHandle, int uiKeyBits, byte[] pucKey, int puiKeyLength) {
        // 参数校验
        isCheckSessionHandle(sessionHandle);
        if (uiKeyBits <= 0) {
            throw new BuptException(BuptErrorCodeEnum.BUPT_PUI_KEY_LENGTH_ZERO.getDescription());
        }
        if (pucKey == null) {
            throw new BuptException(BuptErrorCodeEnum.BUPT_PUCKEY_ERROR.getDescription());
        }
        if (puiKeyLength <= 0) {
            throw new BuptException(BuptErrorCodeEnum.BUPT_PUI_KEY_LENGTH_ZERO.getDescription());
        }

        // 创建一个long数组用于接收密钥句柄
        long[] phKeyHandle = new long[1];
        int status = instance.SDF_ImportKeyWithISK_RSA(sessionHandle, uiKeyBits, pucKey, puiKeyLength, phKeyHandle);
        if (BuptConstant.OK == status) {
            return BuptResultDto.ok(phKeyHandle[0]);
        }
        return BuptResultDto.error(status);
    }

    /**
     * 6.3.20
     * 功能描述：销毁会话密钥，并释放为密钥句柄分配的内存资源
     * 参数： hSessionHandle【in】 已经打开设备会话句柄
     * hKeyHandle[in]     返回的密钥句柄
     * 返回值：0  成功； 非0  失败，返回错误代码
     * 备注： 在对称算法运算完成后，应调用本函数销毁会话密钥
     **/
    public static BuptResultDto generateKeyWithEPKECC(long hSessionHandle, long hKeyHandle) {
        // 参数校验
        isCheckSessionHandle(hSessionHandle);

        // 销毁会话密钥
        int status = instance.SDF_DestroyKey(hSessionHandle, hKeyHandle);
        return BuptConstant.OK == status ? BuptResultDto.ok() : BuptResultDto.error(status);
    }

    /**
     * 6.4.1
     * 功能描述：指定使用外部公钥RSA对数据进行运算
     * 参数： hSessionHandle【in】      与设备建立的会话句柄
     * pucPublicKey[in]          外部RSA公钥结构
     * pucDataInput[in]          缓冲器指针，用于存放输入的数据
     * uiInputLength[in]         输入数据长度
     * pucDataOutput[out]        缓冲器指针，用于存放输出的数据
     * puiOutputLength[out]      输出数据长度
     * 返回值：0  成功； 非0  失败，返回错误代码
     * 备注： 数据格式由应用层封装
     **/
    public static BuptResultDto<OutDataBo> externalPublicKeyOperationRSA(long hSessionHandle, RSArefPublicKey pucPublicKey,
                                                                         byte[] pucDataInput, int uiInputLength) {
        // 参数校验
        isCheckSessionHandle(hSessionHandle);

        // 输出数据
        byte[] pucDataOutput = new byte[16];
        // 数据长度
        int[] puiOutputLength = new int[1];
        int status = instance.SDF_ExternalPublicKeyOperation_RSA(hSessionHandle, pucPublicKey, pucDataInput, uiInputLength, pucDataOutput, puiOutputLength);
        if (BuptConstant.OK == status) {
            OutDataBo encDataBo = new OutDataBo();
            encDataBo.setPucDataOutput(pucDataOutput);
            encDataBo.setPuiOutputLength(puiOutputLength[0]);
            return BuptResultDto.ok(encDataBo);
        }
        return BuptResultDto.error(status);
    }

    /**
     * 6.4.3
     * 功能描述：指定使用内部指定RSA私钥对数据进行运算
     * 参数： hSessionHandle【in】      与设备建立的会话句柄
     * uiKeyIndex[in]            密码设备内部存储私钥的索引值(RSA:1)
     * pucDataInput[in]          缓冲器指针，用于存放输入的数据
     * uiInputLength[in]         输入数据长度
     * pucDataOutput[out]        缓冲器指针，用于存放输出的数据
     * puiOutputLength[out]      输出数据长度
     * 返回值：0  成功； 非0  失败，返回错误代码
     * 备注：  索引范围仅限于内部签名密钥对，数据格式由应用层封装
     **/
    public static BuptResultDto<OutDataBo> internalPublicKeyOperationRSA(long hSessionHandle, int uiKeyIndex, byte[] pucDataInput, int uiInputLength) {
        // 参数校验
        isCheckSessionHandle(hSessionHandle);

        // 输出数据
        byte[] pucDataOutput = new byte[16];
        // 数据长度
        int[] puiOutputLength = new int[1];
        int status = instance.SDF_InternalPrivateKeyOperation_RSA(hSessionHandle, uiKeyIndex, pucDataInput, uiInputLength, pucDataOutput, puiOutputLength);
        if (BuptConstant.OK == status) {
            OutDataBo encDataBo = new OutDataBo();
            encDataBo.setPucDataOutput(pucDataOutput);
            encDataBo.setPuiOutputLength(puiOutputLength[0]);
            return BuptResultDto.ok(encDataBo);
        }
        return BuptResultDto.error(status);
    }

    /**
     * 6.5.1
     * 功能描述：使用指定的密钥句柄和IV对数据进行加密运算
     * 参数： hSessionHandle【in】      与设备建立的会话句柄
     * hKeyHandle[in]            指定密钥句柄
     * uiAlgID[in]               算法标识，指定对称加密算法（参考AlgorithmConstants常量定义）
     * pucIV[in|out]             缓冲区指针，用于存放输入和输出的IV向量（16字节）
     * pucData[in]               缓冲器指针，用于存放输入的明文数据 （单次加密上限8k[8192]）
     * uiDataLength[in]          输入数据长度
     * pucEncData[out]           缓冲器指针，用于存放输出的数据密文
     * puiEncDataLength[out]     输出数据长度
     * 返回值：0  成功； 非0  失败，返回错误代码
     * 备注： 此函数不对数据进行填充处理，输入的数据必须是指定算法分组长度的整数倍。
     **/
    public static BuptResultDto<EncDataBo> encrypt(long sessionHandle, long hKeyHandle, int uiAlgID, byte[] pucIV, String planStr) {
        // 参数校验
        isCheckSessionHandle(sessionHandle);
        isCheckKeyHandle(hKeyHandle);
        byte[] plain = getPaddedBytesPKCS7(planStr);
        // 密文数据
        byte[] pucEncData = new byte[plain.length*2];
        // 密文数据长度
        int[] puiEncDataLength = new int[1];
        int status = instance.SDF_Encrypt(sessionHandle, hKeyHandle, uiAlgID, pucIV, plain, plain.length, pucEncData, puiEncDataLength);
        if (BuptConstant.OK == status) {
            EncDataBo encDataBo = new EncDataBo();
            encDataBo.setPucIV(pucIV);
            pucEncData = resetDataArray(pucEncData, puiEncDataLength[0]);
            encDataBo.setPucEncData(pucEncData);
            encDataBo.setPuiEncDataLength(puiEncDataLength[0]);
            return BuptResultDto.ok(encDataBo);
        }
        return BuptResultDto.error(status);
    }

    /**
     * 6.5.2
     * 功能描述：使用指定的密钥句柄和IV对数据进行对称解密运算
     * 参数： hSessionHandle【in】             与设备建立的会话句柄
     * hKeyHandle[in ]            指定的密钥句柄
     * uiAlgID[in]                算法标识，指定对称加密算法
     * pucIV[in|out]              缓冲区指针，用于存放输入和返回的IV 数据
     * pucEncData[in]             缓冲区指针，用于存放输入的数据密文
     * uiEncDataLength[in]        输入的数据密文长度
     * pucData[out]               缓冲区指针用于存放输出的数据明文
     * puiDataLength [out]        输出的数据明文长度
     * 返回值：0  成功； 非0  失败，返回错误代码
     * 备注： 此函数不对数据进行填充处理，输入的数据必须是指定算法分组长度的整数倍。
     **/
    public static BuptResultDto<DecDataBo> decrypt(long sessionHandle, long hKeyHandle, int uiAlgID, byte[] pucIV, byte[] pucEncData, int puiEncDataLength) {
        // 参数校验
        isCheckSessionHandle(sessionHandle);
        isCheckKeyHandle(hKeyHandle);

        // 密文数据
        byte[] pucData = new byte[puiEncDataLength*2];
        // 密文数据长度
        int[] uiDataLength = new int[1];
        int status = instance.SDF_Decrypt(sessionHandle, hKeyHandle, uiAlgID, pucIV, pucEncData, puiEncDataLength, pucData, uiDataLength);
        if (BuptConstant.OK == status) {
            DecDataBo decDataBo = new DecDataBo();
            pucData = resetDataArray(pucData, uiDataLength[0]);
            pucData = removePaddingPKCS7(pucData);
            decDataBo.setPucData(pucData);
            decDataBo.setPuiDataLength(uiDataLength[0]);
            return BuptResultDto.ok(decDataBo);
        }
        return BuptResultDto.error(status);
    }

    public static BuptResultDto generateKeyWithIPKRSA(long sessionHandle, int uiPKIndex, int uiKeyBits) {
        isCheckSessionHandle(sessionHandle);
        byte[] pucKey = new byte[256];
        // 创建一个int数组用于接收出参
        int[] puiKeyLength = new int[1];

        // 创建一个long数组用于接收出参
        long[] phKeyHandle = new long[1];

        int status = instance.SDF_GenerateKeyWithIPK_RSA(sessionHandle, uiPKIndex, uiKeyBits, pucKey, puiKeyLength, phKeyHandle);
        if (BuptConstant.OK == status) {
            RSASessionKeyBo sessionKeyBo = new RSASessionKeyBo();
            sessionKeyBo.setPucKey(pucKey);
            sessionKeyBo.setPuiKeyLength(puiKeyLength[0]);
            sessionKeyBo.setPhKeyHandle(phKeyHandle[0]);
            return BuptResultDto.ok(sessionKeyBo);
        }

        return BuptResultDto.error(status);
    }

    /**
     * 判断字符串中是否包含中文字符
     *
     * @param input 输入字符串
     * @return true 表示包含中文，false 表示不包含中文
     */
    public static boolean containsChinese(String input) {
        for (char c : input.toCharArray()) {
            // 中文字符范围：\u4E00 至 \u9FFF
            if (c >= 0x4E00 && c <= 0x9FFF) {
                return true;
            }
        }
        return false;
    }


    /**
     * 将输入的字符串填充为 16 的倍数，使用 UTF-8 编码，兼容中文。
     *
     * @param input 输入字符串
     * @return 填充后的字节数组
     */
    public static byte[] getPaddedBytes(String input) {
        // 将输入字符串转换为 UTF-8 编码的字节数组
        byte[] plain = input.getBytes(StandardCharsets.UTF_8);

        // 判断是否包含中文字符
        boolean hasChinese = containsChinese(input);

        int blockSize = 16;
        int paddingLength = blockSize - (plain.length % blockSize); // 计算需要填充的字节数

        // 不包含中文时，只填充 0 直到长度为 16
        if (!hasChinese) {
            if (paddingLength == blockSize) {
                return plain;  // 长度已经是 16 的倍数，无需填充
            }
            byte[] paddedPlain = new byte[plain.length + paddingLength];
            System.arraycopy(plain, 0, paddedPlain, 0, plain.length);  // 拷贝原始数据
            return paddedPlain;  // 返回填充后的字节数组（默认填充的字节值是 0）
        }

        // 包含中文时，使用 PKCS5/PKCS7 填充
        if (paddingLength == blockSize) {
            paddingLength = 0;  // 已经是 16 的倍数，按 PKCS 规则仍需填充一个完整的块
        }
        byte[] padding = new byte[paddingLength];
        Arrays.fill(padding, (byte) paddingLength); // 使用 PKCS7 的填充方式

        byte[] paddedPlain = new byte[plain.length + paddingLength];
        System.arraycopy(plain, 0, paddedPlain, 0, plain.length);  // 拷贝原始数据
        System.arraycopy(padding, 0, paddedPlain, plain.length, paddingLength);  // 添加填充数据

        return paddedPlain;

    }


    /**
     * 使用 PKCS#7 填充标准对输入字符串进行填充，确保返回的字节数组长度是 16 的倍数。
     *
     * @param input 需要填充的输入字符串
     * @return 填充后的字节数组
     */
    public static byte[] getPaddedBytesPKCS7(String input) {
        byte[] plain = input.getBytes(StandardCharsets.UTF_8);
        int blockSize = 16;
        int paddingLength = blockSize - (plain.length % blockSize);

        // PKCS#7 填充
        byte[] padding = new byte[paddingLength];
        Arrays.fill(padding, (byte) paddingLength);

        byte[] paddedPlain = new byte[plain.length + paddingLength];
        System.arraycopy(plain, 0, paddedPlain, 0, plain.length);
        System.arraycopy(padding, 0, paddedPlain, plain.length, paddingLength);

        return paddedPlain;
    }

    /**
     * 根据 PKCS#7 填充标准去除填充，恢复原始数据。
     *
     * @param paddedBytes 填充后的字节数组
     * @return 去除填充后的原始字节数组
     * @throws IllegalArgumentException 如果填充不合法
     */
    public static byte[] removePaddingPKCS7(byte[] paddedBytes) {
        if (paddedBytes.length == 0) {
            return paddedBytes;
        }

        int paddingLength = paddedBytes[paddedBytes.length - 1];  // 获取最后一个字节的值作为填充长度
        if (paddingLength < 1 || paddingLength > 16) {
            throw new IllegalArgumentException("Invalid padding length");
        }

        // 验证填充的有效性
        for (int i = 1; i <= paddingLength; i++) {
            if (paddedBytes[paddedBytes.length - i] != paddingLength) {
                throw new IllegalArgumentException("Invalid padding");
            }
        }

        // 去除填充
        return Arrays.copyOf(paddedBytes, paddedBytes.length - paddingLength);
    }

    /**
     * @desc 去除填充，兼容中文
     *
     * @param paddedData 解密后的明文-带填充的数据
     * @return 去除填充后的字节数组
     */
    public static byte[] removePadding(byte[] paddedData) {
        if (paddedData == null) {
            return null;
        }

        int length = paddedData.length;
        if (length == 0) {
            return paddedData;
        }

        // 获取最后一个字节，它表示填充的字节数
        byte paddingValue = paddedData[length - 1];
        int paddingLength = paddingValue & 0xFF; // 转换为整数

        // 检查填充的有效性
        if (paddingLength > 0 && paddingLength <= length) {
            // 检查填充是否正确
            for (int i = 0; i < paddingLength; i++) {
                if (paddedData[length - 1 - i] != paddingValue) {
                    throw new IllegalArgumentException("Invalid padding detected");
                }
            }
            return Arrays.copyOf(paddedData, length - paddingLength);
        } else {
            throw new IllegalArgumentException("Invalid padding length");
        }
    }


    private static byte[] resetDataArray(byte[] dataArray, int length) {
        return Arrays.copyOf(dataArray, length);
    }

}
